package com.andy.wang.controller;

import com.alibaba.fastjson.JSONObject;
import com.andy.wang.pojo.*;
import com.andy.wang.service.AccroomService;
import com.andy.wang.service.RoomauditService;
import com.andy.wang.service.RoomchitchatService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import jakarta.websocket.*;
import jakarta.websocket.server.PathParam;
import jakarta.websocket.server.ServerEndpoint;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

@Component
@Slf4j
@ServerEndpoint("/webSocketRoomMessage/{rid}/{username}/{userID}") //暴露的ws应用的路径
public class WebSocketRoomMessage implements ApplicationContextAware {
    /**
     * 当前用户进入的房间号
     */
    public static int rid = 0;
    private static ApplicationContext applicationContext;
    /**
     * 当前在线客户端数量（线程安全的）
     */
    private static AtomicInteger onlineClientNumber = new AtomicInteger(0);
    /**
     * 当前在线客户端集合（线程安全的）：以键值对方式存储，key是连接的编号，value是连接的对象
     */
    private static Map<String, Session> onlineClientMap = new ConcurrentHashMap<>();
    /**
     * 当前用户进入的房间号的其他用户ID
     */
    private static ArrayList<String> userIds = null;
    private static int userid = 0;

    /**
     * 获取 applicationContext
     *
     * @return
     */
    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        WebSocketRoomMessage.applicationContext = applicationContext;
    }

    /**
     * 客户端与服务端连接成功
     *
     * @param session
     * @param username
     */
    @OnOpen
    public static void onOpen(Session session, @PathParam("rid") int rid2, @PathParam("username") String username, @PathParam("userID") String userID) {
        /*
            do something for onOpen
            与当前客户端连接成功时
         */
        userid = Integer.parseInt(userID);
        rid = rid2;
        onlineClientNumber.incrementAndGet();//在线数+1
        onlineClientMap.put(userID, session);//添加当前连接的session
        log.info("时间[{}]：与用户[{}]的连接成功，当前连接编号[{}]，当前连接总数[{}],房间号[{}]",
                new Date().toLocaleString(),
                username,
                userID,
                onlineClientNumber,
                rid);
    }


    /**
     * 客户端与服务端连接关闭
     *
     * @param session
     * @param username
     */
    @OnClose
    public static void onClose(Session session,@PathParam("username") String username,@PathParam("userID") String userID) {
        /*
            do something for onClose
            与当前客户端连接关闭时
         */
        onlineClientNumber.decrementAndGet();//在线数-1
        onlineClientMap.remove(session.getUserProperties().get("userId"));//移除当前连接的session
        log.info("时间[{}]：与用户[{}]的连接关闭，当前连接编号[{}]，当前连接总数[{}]",
                new Date().toLocaleString(),
                username,
                session.getId(),
                onlineClientNumber);
    }

    /**
     * 客户端与服务端连接异常
     *
     * @param error
     * @param session
     * @param username
     */
    @OnError
    public static void onError(Throwable error, Session session, @PathParam("username") String username) {
        /*
            do something for onError
            与当前客户端连接异常时
         */
        error.printStackTrace();
    }

    /**
     * 客户端向服务端发送消息
     *
     * @param message
     * @param userID
     * @throws IOException
     */
    @OnMessage
    public static void onMsg(Session session, String message, @PathParam("username") String username, @PathParam("userID") String userID, @PathParam("uphoto") String uphoto, @PathParam("type") String type,@PathParam("UploadFile")String UploadFile,@PathParam("msgSVG")String msgSVG) throws IOException {
        /*
            do something for onMessage
            收到来自当前客户端的消息时
         */
        log.info("时间[{}]：来自连接编号为[{}]的消息：[{}]",
                new Date().toLocaleString(),
                userID,
                message);
        if(JSONObject.parseObject(message).get("type").equals("1")){
            roomMessage(message,userID);
        }else if(JSONObject.parseObject(message).get("type").equals("2")){
            System.out.println("正在发送图片");
            RoomchitchatService roomchitchatService = getApplicationContext().getBean(RoomchitchatService.class);
            // 添加的聊天历史表
            Roomchitchat roomchitchat = new Roomchitchat();
            roomchitchat.setChitchatIn(Integer.valueOf(userID));
            roomchitchat.setMessageIMG((String) JSONObject.parseObject(message).get("UploadFile"));
            roomchitchatService.save(roomchitchat);

            // 添加到聊天图片审核表
            RoomauditService roomauditService = getApplicationContext().getBean(RoomauditService.class);
            Roomaudit roomaudit = new Roomaudit();
            roomaudit.setUID(Integer.valueOf(userID));
            roomaudit.setAuditIMG((String) JSONObject.parseObject(message).get("UploadFile"));
            roomauditService.save(roomaudit);

            roomMessage(message,userID);
        }else if(JSONObject.parseObject(message).get("type").equals("3")){
            System.out.println("视频上传成功-------------------");
            System.out.println(JSONObject.parseObject(message).get("msgSVG"));

            RoomchitchatService roomchitchatService = getApplicationContext().getBean(RoomchitchatService.class);
            // 添加的聊天历史表
            Roomchitchat roomchitchat = new Roomchitchat();
            roomchitchat.setChitchatIn(Integer.valueOf(userID));
            roomchitchat.setMessageSVG((String) JSONObject.parseObject(message).get("msgSVG"));
            roomchitchatService.save(roomchitchat);

            // 添加到聊天图片审核表
            RoomauditService roomauditService = getApplicationContext().getBean(RoomauditService.class);
            Roomaudit roomaudit = new Roomaudit();
            roomaudit.setUID(Integer.valueOf(userID));
            roomaudit.setAuditSVG((String) JSONObject.parseObject(message).get("msgSVG"));
            roomauditService.save(roomaudit);

            roomMessage(message,userID);
        }
    }

    //向所有客户端发送消息（广播）
    private static void sendAllMessage(String message) {
        Set<String> sessionIdSet = onlineClientMap.keySet(); //获得Map的Key的集合
        for (String sessionId : sessionIdSet) { //迭代Key集合
            Session session = onlineClientMap.get(sessionId); //根据Key得到value
            session.getAsyncRemote().sendText(message); //发送消息给客户端
        }
    }

    //给指定客户端发送消息，通过UserID和连接编号找到Session发送       // 连接编号添加的是用户ID
    private static void roomMessage(String obj, String userID) {
        LambdaQueryWrapper<Accroom> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.select(Accroom::getEnteredRoom)
                .eq(Accroom::getRid, rid);
        AccroomService accroomService = getApplicationContext() .getBean(AccroomService.class);
        List<Accroom> userList = accroomService.list(lambdaQueryWrapper);
        userIds = new ArrayList<>();
        for (Accroom accroom : userList) {
            userIds.add(String.valueOf(accroom.getEnteredRoom()));
        }

        try {
            for (Object i : userIds) {
                Session session = onlineClientMap.get(i);
                if (session != null) {
                    session.getAsyncRemote()
                            .sendText(obj);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
    }
}

